home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 25 / Mac Magazin and MacEasy Magazine CD - Issue 25.iso / Grafik & Text / Alpha / Tcl / Menus / eudoraMenu.tcl < prev    next >
Text File  |  1996-08-15  |  23KB  |  875 lines

  1. #     <nowrap>
  2. # Built for Eudora
  3.  
  4. # Class message: A message
  5. # Elements:
  6. #     field by name
  7. # Properties:
  8. #     body  string  -- the body of the message
  9. #     priority  integer  -- the priority
  10. #     label  integer  -- the index of the label
  11. #     status  unread/already read/replied/forwarded/redirected/not sendable/sendable/queued/sent/never sent  -- the message status
  12. #     sender  string  -- the sender as appearing in the message summary
  13. #     date  string  [r/o]  -- the date as appearing in the message summary
  14. #     subject  string  -- the subject as appearing in the message summary
  15. #     size  integer  [r/o]  -- the size of the message
  16. #     outgoing  boolean  [r/o]  -- is the message is outgoing?
  17. #     signature  none/standard/alternate  -- which signature the message should have
  18. #     QP  boolean  -- is Eudora allowed to encode text?
  19. #     return receipt  boolean  -- is a return receipt is requested?
  20. #     wrap  boolean  -- should the text be wrapped when sent?
  21. #     tab expansion  boolean  -- should tabs get expanded to spaces?
  22. #     keep copy  boolean  -- should a copy should be kept after message is sent?
  23. #     preserve macintosh info  boolean  -- should Macintosh information always be sent with attachments?
  24. #     attachment encoding  AppleDouble/AppleSingle/BinHex/uuencode  -- the type of encoding to use for attachments
  25. #     show all headers  boolean  -- should all headers be visible?
  26. #     transliteration table  integer  -- the resource id of the transliteration table
  27. #     will be fetched  boolean  -- will the message be [re]fetched on next check?
  28. #     will be deleted  boolean  -- will the message be deleted from server on next check?
  29.  
  30. if $startingUp {
  31.     set mailMenu         "•138"
  32.     addMenu mailMenu
  33.     return
  34. }
  35.  
  36.  
  37.  
  38. proc mailMenu {} {}
  39. proc dummyMail {} {}
  40.  
  41.  
  42. addMode Mail dummyMail {} mailMenu
  43.  
  44. if {![info exists trashName]} {set trashName "Trash"}
  45.  
  46. newModeVar Mail wordBreak {(\$)?[a-zA-Z0-9_.]+} 0
  47. newModeVar Mail wordWrap {0} 1
  48. newModeVar Mail wordBreakPreface {[^a-zA-Z0-9_\$]} 0
  49. newModeVar Mail autoMark    0    1
  50. set mailKeywords {{Subject:} {To:} {From:} {Cc:} {Date:} {Sender:}}
  51. regModeKeywords -k blue -e {>} Mail $mailKeywords
  52.  
  53.  
  54. #================================================================================
  55.  
  56.  
  57. #===============================================================================
  58. newModeVar Mail tossOnQueue        1    1
  59. newModeVar Mail    switchOnQueue    0    1
  60. #===============================================================================
  61. # Utility routines.
  62. proc eudoraFolder {} { nameObject euMF {'TEXT'()} [nullObject] }
  63. proc mailboxByName {name} { nameObject euMB "“$name”" [eudoraFolder] }
  64. proc mailboxByIndex {ind} { indexObject euMB $ind [eudoraFolder] }
  65. proc eudoraMessage {msg_id mailbox} { indexObject euMS $msg_id [mailboxByName $mailbox] }
  66. proc mailboxProperty {prop mailbox} { objectProperty 'CSOm' $prop [mailboxByName $mailbox] }
  67. proc messageProperty {prop msg_id mailbox} { objectProperty 'CSOm' $prop [eudoraMessage $msg_id $mailbox] }
  68.  
  69. # Get path-name for indicated mailbox
  70. proc mailboxPathName {name} {
  71.     extractPath [mailboxProperty euFS $name]
  72. }
  73.  
  74. proc mailboxPathIndex {ind} {
  75.     set res [objectProperty 'CSOm' euFS [mailboxByIndex $ind]]
  76.     return [extractPath $res]
  77. }
  78.  
  79. #===============================================================================
  80.  
  81.  
  82. proc checkMailPath {} {
  83.     set name [nameFromAppl CSOm]
  84.     launch $name
  85.     return [file tail $name]
  86. }
  87.  
  88. if {![info exists eudoraBoxes]} {
  89.     set eudoraBoxes {In Out}
  90. }
  91.  
  92. menu -n $mailMenu -p eudoraProc {
  93.     "<SbackgroundEudora"
  94.     "<Seudora"
  95.     "help"
  96.     "palette"
  97.     "(-"
  98.     "/e<UnewMessage"
  99.     "cc"
  100.     "bcc"
  101.     "(-"
  102.     "/f<Usend"
  103.     "/g<Ureply"
  104.     "(-"
  105.     "/,<SfinishNickname"
  106.     "/,<S<O<IsubstituteNickname"
  107.     "editNicknames"
  108.     "updateNicknames"
  109.     "(-"
  110.     "updateMailboxLists"
  111.     {menu -n open -p mailBoxProc -m {}}
  112.     {menu -n moveTo -p transferProc -m {}}
  113.     "(-"
  114.     {menu -n tellEudora -p eudoraProc {
  115.         "/k<UflushOutbox"
  116.         "/l<UcheckForMail"
  117.         "(-"
  118.         startNotifying
  119.         stopNotifying}}
  120.     {menu -n mailFlags -p mailFlagsProc {alertOnIncoming flushOnCheck immediateSend -- trashName}}
  121. }
  122. menu -n open -p mailBoxProc -m [concat [list "/h<UOpen Mailbox…" "(-"] $eudoraBoxes]
  123. menu -n moveTo -p transferProc -m [concat [list "/i<UMove To Trash" "/j<UMove To Mailbox…" "(-"] $eudoraBoxes]
  124.  
  125. if {![info exists eudoraNicknames] && [file exists "[file dirname [file dirname $PREFS]]:Eudora Folder:Eudora Nicknames"]} {
  126.     set eudoraNicknames "[file dirname [file dirname $PREFS]]:Eudora Folder:Eudora Nicknames"
  127. }
  128.  
  129.  
  130. proc updateNicknames {{arg ""}} {
  131.     global euNicknames eudoraNicknames
  132.     
  133.     if {![info exists eudoraNicknames] || ![file exists $eudoraNicknames]} {
  134.         if {![string length $arg]} {
  135.             alertnote {Please locate the file "Eudora Nicknames" via "Config:App Paths".}
  136.         }
  137.         return
  138.     }
  139.     
  140.     set fd [open $eudoraNicknames]
  141.     foreach a [split [read $fd] "\n"] {
  142.         if {[llength $a]} {
  143.             set euNicknames([lindex $a 1]) [lindex $a 2]
  144.         }
  145.     }
  146.     close $fd
  147. }
  148. updateNicknames quiet
  149.  
  150.  
  151. proc finishNickname {} {
  152.     global euNicknames
  153.     set pos [getPos]
  154.     backwardWord
  155.     set text [getText [getPos] $pos]
  156.     goto $pos
  157.     foreach w [array names euNicknames] {
  158.         if {[string match "$text*" $w]} {
  159.             lappend matches $w
  160.         }
  161.     }
  162.     if {![llength $matches]} {
  163.         beep
  164.     } else {
  165.         insertText [string range [largestPrefix $matches] [string length $text] end]
  166.     }
  167. }    
  168.  
  169.  
  170. proc editNicknames {} {
  171.     global eudoraNicknames
  172.     
  173.     edit "$eudoraNicknames"
  174. }
  175.  
  176.  
  177. proc substituteNickname {} {
  178.     global euNicknames
  179.     finishNickname
  180.     set to [getPos]
  181.     backwardWord
  182.     set from [getPos]
  183.     set text [getText $from $to]
  184.     goto $to
  185.  
  186.     if {[info exists euNicknames($text)]} {
  187.         replaceText $from $to [set euNicknames($text)]
  188.     }
  189. }
  190.  
  191. proc openMailbox {} {
  192.     global eudoraBoxes eudoraLastFolder modifiedVars
  193.     if {[info exists eudoraLastFolder]} {
  194.         set fold $eudoraLastFolder
  195.     } else {
  196.         set fold [lindex $eudoraBoxes 0]
  197.     }
  198.     set eudoraLastFolder [sPromptChoices "Open mailbox" $fold $eudoraBoxes]
  199.     mailBoxProc dummy $eudoraLastFolder
  200.     lappend modifiedVars eudoraLastFolder
  201. }
  202.  
  203.  
  204. proc moveToFolderProc {curr c} {
  205.     global eudoraBoxes
  206.     if {$c != "\t"} {return $c}
  207.     
  208.     set matches {}
  209.     foreach w $eudoraBoxes {
  210.         if {[string match "$curr*" $w]} {
  211.             lappend matches $w
  212.         }
  213.     }
  214.     if {![llength $matches]} {
  215.         beep
  216.     } else {
  217.         return [string range [largestPrefix $matches] [string length $curr] end]
  218.     }
  219.     return ""
  220. }
  221.  
  222.  
  223. proc moveToMailbox {} {
  224.     global eudoraLastFolder modifiedVars trashName
  225.     
  226.     if {[info exists eudoraLastFolder]} {
  227.         set fold $eudoraLastFolder
  228.     } else {
  229.         set fold $trashName
  230.     }
  231.     
  232.     set folder [statusPrompt -f "Move to ($fold): " moveToFolderProc]
  233.     if {[string length $folder]} {
  234.         doFolderMove $folder
  235.         set eudoraLastFolder $folder
  236.         lappend modifiedVars eudoraLastFolder
  237.     } else {
  238.         doFolderMove $fold
  239.     }
  240. }
  241.  
  242.  
  243. proc eudoraProc {menu item} {
  244.     global HOME mailMenu
  245.  
  246.     switch $item {
  247.         "eudora"        {launchForeAppl CSOm}
  248.         "backgroundEudora"        {launch [nameFromAppl CSOm]}
  249.         "help"            {edit -r "$HOME:Help:Eudora"}
  250.         "palette"        {float -m $mailMenu -M 2 -n Eudora}
  251.         "cc"            {eudoraCc}
  252.         "bcc"            {eudoraBcc}
  253.         "newMessage"    {mailNewMsg}
  254.         "reply"            {mailReplymsg}
  255.         "send"            {checkMailPath; mailSendCreatedMsg}
  256.         "flushOutbox"    {checkMailPath; mailFlushOut}
  257.         "checkForMail"    {checkMailPath; mailCheck}
  258.         "startNotifying" "checkMailPath; startNotifying"
  259.         "stopNotifying"    "checkMailPath; stopNotifying"
  260.         "moveToTrash"    {mailTrashmsg}
  261.         "Move To Trash"    {mailTrashmsg}
  262.         "Create New"    {eudoraNewMailbox}
  263.         "Delete"        {eudoraDeleteMailbox}
  264.         default            $item
  265.     }
  266. }
  267.  
  268. if {![info exists mailflushOnCheck]} {set mailflushOnCheck 1}
  269. if {![info exists mailalertOnIncoming]} {set mailalertOnIncoming 1}
  270. if {![info exists mailimmediateSend]} {set mailimmediateSend 0}
  271. markMenuItem mailFlags flushOnCheck $mailflushOnCheck
  272. markMenuItem mailFlags alertOnIncoming $mailalertOnIncoming
  273. markMenuItem mailFlags immediateSend $mailimmediateSend
  274.  
  275.  
  276. proc mailFlagsProc {menu flag} {
  277.     global mail$flag modifiedVars trashName
  278.  
  279.     if {$flag == "trashName"} {
  280.         set trashName [prompt "Trash folder name:" $trashName]
  281.         lappend modifiedVars trashName
  282.         return
  283.     }
  284.     
  285.  
  286.     set mail$flag [expr 1 - [set mail$flag]]
  287.     lappend modifiedVars mail$flag
  288.     markMenuItem mailFlags $flag [set mail$flag]
  289. }
  290.  
  291.  
  292. proc mailBoxProc {menu item} {
  293.     global inboxMembers ALPHA eudoraBoxes modifiedVars
  294.     global tileLeft tileTop tileHeight errorHeight defWidth
  295.  
  296.     if {$item == "Open Mailbox"} {
  297.         return [openMailbox]
  298.     }
  299.     
  300.     killMailboxWindow
  301.  
  302.     checkMailPath
  303.     switchTo $ALPHA
  304.  
  305.     global trashedMsgs$item
  306.     set trashedMsgs$item {}
  307.     
  308.     set inboxMembers {}
  309.     set text {}
  310.     set ind 1
  311.     foreach msg [mailSenders $item] {
  312.         set from [mailAddr [lindex $msg 0]]
  313.         set tag {}
  314.         while {[lsearch $inboxMembers $from$tag] >= 0} {
  315.             if {![string length $tag]} {
  316.                 set tag { <2>}
  317.             } else {
  318.                 regexp {[0-9]+} $tag tag
  319.                 set tag " <[expr $tag + 1]>"
  320.             }
  321.         }
  322.         append text [format "%-40s : %s\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$item∞$ind\r" "$from$tag" [lindex $msg 1]]
  323.         lappend inboxMembers $from$tag
  324.         incr ind
  325.     }
  326.     if {![string length $text]} {
  327.         alertnote "No messages in '$item'!"
  328.         return
  329.     }
  330.     
  331.     new -n "* MAILBOX '$item' *" -g $tileLeft $tileTop $defWidth $errorHeight
  332.     global winModes
  333.     set name [lindex [winNames] 0]
  334.     changeMode [set winModes($name) Brws]
  335.  
  336.     insertText "(<cr> to go to message)\r-----\r$text"
  337.     
  338.     select [nextLineStart [nextLineStart 0]] [nextLineStart [nextLineStart [nextLineStart 0]]]
  339.     setWinInfo dirty 0
  340.     setWinInfo read-only 1
  341.     message ""
  342. }
  343.  
  344. proc eudoraNewMailbox {} {
  345. }
  346.  
  347.  
  348. proc eudoraDeleteMailbox {} {
  349. }
  350.  
  351.  
  352. proc killMailboxWindow {} {
  353.     if {[set ind [lsearch [winNames] {*MAILBOX*}]] >= 0} {
  354.         set win [lindex [winNames] $ind]
  355.         bringToFront $win
  356.         killWindow
  357.     }
  358. }
  359.  
  360.  
  361. proc mailGotoMatch {} {
  362.     if {[regexp {∞(.+)∞([0-9]+)} [getText [lineStart [getPos]] [nextLineStart [getPos]]] dummy folder ind]} {
  363.         global trashedMsgs$folder
  364.         
  365.         set deleted 0
  366.         for {set i 1} {$i < $ind} {incr i} {
  367.             if {[lsearch [set trashedMsgs$folder] $i] >= 0} {
  368.                 incr deleted
  369.             }
  370.         }
  371.         mailOpen $folder [expr $ind - $deleted] $ind
  372.     }
  373. }
  374.  
  375.  
  376. proc mailAddr {name} {
  377.     if {![regexp {<(.*)>} $name dummy addr]} {
  378.         regexp {^[^ ]+} $name addr
  379.     }
  380.     return $addr
  381. }
  382.  
  383.  
  384. proc mailSenders {folder} {
  385.     set cnt [mailCountMsgs $folder]
  386.     set msgs {}
  387.     for {set i 1} {$i <= $cnt} {incr i} {
  388.         set subject {}
  389.         if {![regexp -nocase {From: (.*)} [mailGetField from $folder $i] dummy from]} {
  390.             error "No from field!"
  391.         }
  392.         regexp {Subject: (.*)} [mailGetField subject $folder $i] dummy subject
  393.         lappend msgs [list $from $subject]
  394.     }
  395.     return $msgs
  396. }    
  397.  
  398.  
  399. proc eudoraCc {} {
  400.     if {![catch {set res [search -s -f 1 -r 1 -i 1 {cc:.*} 0]}]} {
  401.         goto [lindex $res 0]
  402.         endOfLine
  403.     } else {
  404.         beginningOfBuffer
  405.         nextLine
  406.         insertText "Cc: \r"
  407.         backwardChar
  408.     }
  409. }
  410.  
  411.  
  412. proc eudoraBcc {} {
  413.     if {![catch {set res [search -s -f 1 -r 1 -i 1 {bcc:.*} 0]}]} {
  414.         goto [lindex $res 0]
  415.         endOfLine
  416.     } else {
  417.         beginningOfBuffer
  418.         nextLine
  419.         insertText "Bcc: \r"
  420.         backwardChar
  421.     }
  422. }
  423.  
  424.  
  425. proc mailFlushOut {} {
  426.     global MailmodeVars
  427.     message "Telling Eudora to flush messages…"
  428.  
  429.     AEBuild 'CSOm' CSOm eCon eSen bool(«01») eChk bool(«00»)
  430.     message ""
  431. }
  432.  
  433.  
  434. proc mailCheck {} {
  435.     global MailmodeVars mailflushOnCheck
  436.     message "Told Eudora to check for new mail…"
  437.  
  438.     AEBuild 'CSOm' CSOm eCon eSen bool(«0$mailflushOnCheck») eChk bool(«01»)
  439. }
  440.  
  441.  
  442. proc mailReplymsg {} {
  443.     global inboxMembers
  444.  
  445.     set prefix "> "
  446.     set res [search -s -f 1 -r 1 {^>==} 0]
  447.     set header [getText 0 [lindex $res 0]]
  448.     
  449.     set from [mailGetFrom]
  450.     if {![regexp {Subject: ([^\r]*)} $header dummy subject]} {set subject ""}
  451.     set body [getText [expr [lindex $res 1] + 1] [maxPos]]
  452.  
  453.     regsub -all "\r" $body "\r$prefix" body
  454.     mailNewMsg $from "Re: $subject" "\r$prefix$body\r"
  455. }
  456.  
  457. proc transferProc {menu item} {
  458.     if {$item == "Move To Trash"} {
  459.         mailTrashmsg
  460.     } elseif {$item == "Move To Mailbox"} {
  461.         moveToMailbox
  462.     } else {
  463.         doFolderMove $item
  464.     }
  465. }
  466.  
  467.  
  468. proc mailTrashmsg {} {
  469.     global trashName
  470.     doFolderMove $trashName
  471. }
  472.  
  473. proc doFolderMove {toFolder} {
  474.     # Is this a summary or msg window?
  475.     if {[regexp "MAILBOX" [lindex [winNames] 0]]} {
  476.         if {![regexp {∞(.*)∞([0-9]+)} [getText [getPos] [nextLineStart [getPos]]] dummy folder orig]} {
  477.             beep
  478.             return
  479.         }
  480.         if {$toFolder == $folder} return
  481.         global trashedMsgs$folder
  482.  
  483.         set deleted 0
  484.         for {set i 1} {$i < $orig} {incr i} {
  485.             if {[lsearch [set trashedMsgs$folder] $i] >= 0} {
  486.                 incr deleted
  487.             }
  488.         }
  489.         set number [expr $orig - $deleted]
  490.         set summary 1
  491.     } else {
  492.         set pos [lindex [search -f 1 -r 1 {^Msg} 0] 0]
  493.         set text [getText $pos [nextLineStart $pos]]
  494.         regexp {"([^"]+)" \(([0-9]+)\).*"([^"]+)"} $text dummy number orig folder
  495.         if {$toFolder == $folder} return
  496.         set summary 0
  497.  
  498.         global trashedMsgs$folder
  499.     }
  500.     
  501.     message "Moving msg $number ($orig) of folder '$folder' to '$toFolder'"
  502.     moveMsg $number $folder $toFolder
  503.     if {!$summary} killWindow
  504.  
  505.     lappend trashedMsgs$folder $orig
  506.     
  507.     # Find summary info and delete it
  508.     set win [lindex [winNames] 0]
  509.     if {[regexp "MAILBOX" $win]} {
  510.         setWinInfo read-only 0
  511.     
  512.         set inds [search -f 1 -r 1 "∞$folder∞$orig\$" 0]
  513.         set pos [lindex $inds 0]
  514.         deleteText [lineStart $pos] [nextLineStart $pos]
  515.     
  516.         if {[string length [search -n -f 1 -r 0 {∞} 0]]} {
  517.             setWinInfo dirty 0
  518.             setWinInfo read-only 1
  519.     
  520.             nextLine
  521.             upBrowse
  522.         } else {
  523.             setWinInfo dirty 0
  524.             killWindow
  525.         }
  526.     }
  527. }
  528.  
  529.     
  530. proc mailGetFrom {} {
  531.     set res [search -s -f 1 -r 1 {>==} 0]
  532.     set header [getText 0 [lindex $res 0]]
  533.     if {[regexp {From: ([^\r]*)} $header dummy from]} {
  534.         return [mailAddr $from]
  535.     }
  536.     error "No from line"
  537. }
  538.  
  539.     
  540.  
  541. proc mailSendCreatedMsg {} {
  542.     global MailmodeVars mailimmediateSend
  543.     
  544.     set name [checkMailPath]
  545.     set res [search -s -f 1 -r 0 {>==text follows this line==<} 0]
  546.     set header [getText 0 [lindex $res 0]]
  547.     
  548.     if {![regexp {To: ([^\r]*)} $header dummy to]} {set to ""}
  549.     if {![regexp {Cc: ([^\r]*)} $header dummy cc]} {set cc ""}
  550.     if {![regexp {Subject: ([^\r]*)} $header dummy subject]} {set subject ""}
  551.  
  552.     set body [getText [expr [lindex $res 1] + 1] [maxPos]]
  553.     
  554.     mailCreateMsg
  555.     mailSetField to $to
  556.     mailSetField cc $cc
  557.     mailSetField subject $subject
  558.     mailSetField "" $body
  559.     
  560.     if {$MailmodeVars(tossOnQueue)} {
  561.         setWinInfo dirty 0
  562.         killWindow
  563.     }
  564.  
  565.     mailQueueLast
  566.  
  567.     if {$MailmodeVars(switchOnQueue)} {
  568.         switchTo $name
  569.     }
  570.  
  571.     if {$mailimmediateSend} {
  572.         mailFlushOut
  573.     } else {
  574.         message "Message queued…"
  575.     }
  576. }
  577.  
  578.     
  579. proc mailNewMsg {{to ""} {subject ""} {body ""}} {
  580.     new -n "New Mail"
  581.     global winModes
  582.     set name [lindex [winNames] 0]
  583.     changeMode [set winModes($name) Mail]
  584.  
  585.     insertText "To: $to\rSubject: $subject\r>==text follows this line==<\r$body"
  586.     setWinInfo dirty 0
  587.     goto 0
  588.     centerRedraw
  589.     mailTab
  590. }
  591.  
  592.  
  593. proc mailTab {} {
  594.     global mailKeywords
  595.     if {[catch {search -s -f 1 -r 1 -i 1 "([join $mailKeywords {|}]|^>)" [getPos]} res]} {
  596.         insertText "\t"
  597.         return
  598.     }
  599.     if {[lookAt [lindex $res 0]] == ">"} {
  600.         select [nextLineStart [lindex $res 1]] [maxPos]
  601.     } else {
  602.         goto [expr [lindex $res 1] + 1]
  603.         endLineSelect
  604.     }
  605. }
  606. bind '\t'                         mailTab Mail
  607.  
  608.  
  609. proc mailOpen {folder i originalNum} {
  610.     global tileLeft tileTop tileHeight trashedMsgs$folder defWidth
  611.     
  612.     set from [mailGetField From $folder $i]
  613.     set to [mailGetField To $folder $i]
  614.     set subject [mailGetField Subject $folder $i]
  615.     set sender [mailGetField Sender $folder $i]
  616.     set date [mailGetField Date $folder $i]
  617.     set cc [mailGetField cc $folder $i]
  618.     set contents [mailGetField "" $folder $i]
  619.     
  620. #===============================================================================
  621.     global tileHeight tileTop tileLeft errorHeight errorDisp defWidth
  622.     set top $tileTop
  623.     set geo [getGeometry]
  624.     if {([lindex $geo 0] != $tileLeft) || ([lindex $geo 1] != $top) || ([lindex $geo 2] != $defWidth) || ([lindex $geo 3] != $errorHeight) } {
  625.         moveWin $tileLeft $top
  626.         sizeWin $defWidth $errorHeight
  627.     }
  628.     set mar 28
  629.     incr top [expr $errorHeight + $mar]
  630. #===============================================================================
  631.     new -n "MAIL" -g $tileLeft $top $defWidth [expr $errorDisp - 5]
  632.  
  633.     global winModes
  634.     set name [lindex [winNames] 0]
  635.     changeMode [set winModes($name) Mail]
  636.  
  637.     set text {}
  638.     if {[string length $subject]} {append text "$subject\r"}
  639.     if {[string length $to]} {append text "$to\r"}
  640.     if {[string length $from]} {append text "$from\r"}
  641.     if {[string length $date]} {append text "$date\r"}
  642.     if {[string length $cc]} {append text "$cc\r"}
  643.     if {[string length $sender]} {append text "$sender\r"}
  644.     append text "Msg \"$i\" ($originalNum) of mailbox \"$folder\"     Reply     Trash\r"
  645.     insertText "${text}>===============================================================================
  646. $contents
  647. "
  648.     goto 0
  649.     goto [lindex [search -f 1 -r 1 {^Msg "} 0] 0]
  650.     set pos [getPos]
  651.     regexp -indices {([0-9]+).*mailbox "(.+)".*(Reply).*(Trash)} [getText $pos [nextLineStart $pos]] dummy num fold rep tra
  652.     colorSelectPos [expr $pos + [lindex $num 0]] [expr 1 + $pos + [lindex $num 1]] bold 12
  653.     colorSelectPos [expr $pos + [lindex $fold 0]] [expr 1 +$pos + [lindex $fold 1]] bold 12
  654.     hyperSelectPos [expr $pos + [lindex $rep 0]] [expr 1 +$pos + [lindex $rep 1]] "mailReplymsg"
  655.     hyperSelectPos [expr $pos + [lindex $tra 0]] [expr 1 +$pos + [lindex $tra 1]] "mailTrashmsg"
  656.  
  657.     goto 0
  658.     setWinInfo dirty 0
  659.     setWinInfo read-only 1
  660.     centerRedraw
  661. }
  662.  
  663. proc colorSelectPos {from to ind ind2} {
  664.     insertColorEscape $from $ind
  665.     insertColorEscape $to $ind2
  666. }
  667.  
  668. proc hyperSelectPos {from to text} {
  669.     if {$from == $to} {
  670.         beep
  671.         return
  672.     }
  673.     insertColorEscape $from 3
  674.     insertColorEscape $from 15 $text
  675.     insertColorEscape $to 12
  676.     insertColorEscape $to 0
  677. }
  678.  
  679. proc mailFixMenus {} {
  680.     global mailMenu
  681.     
  682.     set ins {}
  683.     set outs {}
  684.     
  685.     set cnt [mailCountMsgs in]
  686.     for {set i 1} {$i <= $cnt} {incr i} {
  687.         lappend ins [mailGetField from in $i]
  688.     }
  689.     menu -n in {}
  690.     foreach item $ins {
  691.         addMenuItem -l "" in $item
  692.     }
  693.     
  694.     set cnt [mailCountMsgs out]
  695.     for {set i 1} {$i <= $cnt} {incr i} {
  696.         lappend outs [mailGetField from out $i]
  697.     }
  698.     menu -n out {}
  699.     foreach item $outs {
  700.         addMenuItem -l "" out $item
  701.     }
  702. }
  703.  
  704.  
  705. # make message at end of mailbox "out" of mail folder ""
  706. proc mailCreateMsg {} {
  707.     createThingAtEnd 'CSOm' [mailboxByName Out] euMS
  708. }
  709.  
  710.  
  711. # Move msg w/ specified index between folders, including to Trash.
  712. proc moveMsg {msg infolder outfolder} {
  713.     AEBuild -r 'CSOm' core move {----} "obj \{form:indx, want:type(euMS), seld:$msg, from:obj \{form:name, want:type(euMB), seld:“$infolder”, from:obj \{form:name, want:type(euMF), seld:'TEXT'(), from:'null'()\}\}\}" {insh} "insl\{kobj:obj \{form:name, want:type(euMB), seld:“$outfolder”, from:obj \{form:name, want:type(euMF), seld:'TEXT'(), from:'null'()\}\}, kpos:end \}"
  714. }
  715.  
  716.  
  717. # set field "fld" of message 0 to "to"
  718. proc mailSetField {fld to} {
  719.     AEBuild -r 'CSOm' core setd {----} "obj \{form:name, want:type(euFd), seld:“$fld”, from:obj \{form:indx, want:type(euMS), seld:1, from:'null'()\}\}" data "“$to”"
  720. }
  721.  
  722. proc mailGetField {field folder msg} {
  723.     if {[catch {getObjectData 'CSOm' euFd $field [eudoraMessage $msg $folder]} res]} {
  724.         return ""
  725.     } else {
  726.         return $res
  727.     }
  728. }
  729.  
  730. # obj {want:type('prop'), from:obj {form:indx, want:type(euMS), seld:$msg, from:obj {form:name, want:type(euMB), seld:“$folder”, from:obj {form:name, want:type(euMF), seld:'TEXT'(), from:'null'()}}}, form:'prop', seld:type('euST')}
  731.  
  732. proc mailMsgStatus {folder msg} {
  733.     if {[catch {AEBuild -r 'CSOm' core getd {----} "obj \{want:type('prop'), from:obj \{form:indx, want:type(euMS), seld:$msg, from:obj \{form:name, want:type(euMB), seld:“$folder”, from:obj \{form:name, want:type(euMF), seld:'TEXT'(), from:'null'()\}\}\}, form:'prop', seld:type('euST')\}"} text]} {
  734.         return ""
  735.     }
  736.     set from [string first "“" $text]
  737.     set to [string first "”" $text]
  738.     return [string range $text [expr $from + 1] [expr $to - 1]]
  739. }
  740.  
  741. proc mailQueueLast {} {
  742.     AEBuild -r 'CSOm' CSOm eQue ---- {obj {form:indx, want:type(euMS), seld:1, from:'null'()}}
  743. }
  744.  
  745. # CSOm\eAtc{'----':obj {form:indx, want:type(euMS), seld:1, from:'null'()}, eDcl:[fss («486172643A4465736B746F7020466F6C6465723A62756773»)]}
  746. proc mailAttachmentDoesntWork {name} {
  747.     AEBuild -r 'CSOm' CSOm eAtc ---- {obj {form:indx, want:type(euMS), seld:1, from:'null'()}} eDcl [makeAlis $name]
  748. }
  749.  
  750. # core\setd{'----':obj {form:prop, want:type(prop), seld:type(euPY), from:obj {form:indx, want:type(euMS), seld:1, from:'null'()}}, data:1}
  751. proc mailSetNumberProperty {prop to} {
  752.     AEBuild -r 'CSOm' core setd ---- "obj \{form:prop, want:type(prop), seld:type($prop), from:obj \{form:indx, want:type(euMS), seld:1, from:'null'()\}\}" data $to
  753. }    
  754.  
  755.  
  756. proc mailCountMsgs {mbox} {
  757.     return [countObjects 'CSOm' [mailboxByName "$mbox"]  euMS]
  758. }
  759.  
  760. proc mailCountMailboxes {} {
  761.      return [countObjects 'CSOm' [eudoraFolder] euMB]
  762. }
  763.     
  764.  
  765. proc updateMailboxLists {} {
  766.     set num [mailCountMailboxes]
  767.     for {set i 1} {$i <= $num} {incr i} {
  768.         set name [file tail [mailboxPathIndex $i]]
  769.         message $name
  770.         lappend boxes $name
  771.     }
  772.     
  773.     global eudoraBoxes modifiedVars
  774.     lappend modifiedVars eudoraBoxes
  775.     set eudoraBoxes $boxes
  776.     menu -n open -p mailBoxProc -m $eudoraBoxes
  777.     menu -n moveTo -p transferProc -m $eudoraBoxes
  778.     message "done."
  779. }
  780.  
  781.  
  782. #===============================================================================
  783.  
  784. eventHandler CSOm eNot "eudoraHandler"
  785.  
  786. # a sample 'msgs': obj {want:type(euMS), from:obj {want:type(euMB), from:obj {want:type(euMF), from:'null'(), form:name, seld:'TEXT'()}, form:name, seld:“In”}, form:indx, seld:18}, obj {want:type(euMS), from:obj {want:type(euMB), from:obj {want:type(euMF), from:'null'(), form:name, seld:'TEXT'()}, form:name, seld:“In”}, form:indx, seld:19}
  787. proc eudoraHandler {it} {
  788.     global blah mailalertOnIncoming
  789.     message ""
  790.     if {[regexp {eWHp:wArv.*\[(obj.*)\], &repq} $it dum1 msgs]} {
  791.         set ids [getMsgIDs $msgs]
  792.         if {$mailalertOnIncoming} {
  793.             mailBrowser In $ids
  794.             beep; beep
  795.         }
  796.     }
  797. }
  798.  
  799.  
  800. proc mailBrowser {folder ids} {
  801.     global inboxMembers ALPHA
  802.     global tileLeft tileTop defWidth tileHeight errorHeight
  803.  
  804.     checkMailPath
  805.     switchTo $ALPHA
  806.  
  807.     global trashedMsgs$folder
  808.     set trashedMsgs$folder {}
  809.     
  810.     set inboxMembers {}
  811.     set text {}
  812.  
  813.     foreach id $ids {
  814.         regexp {From: (.*)} [mailGetField from $folder $id] dummy from
  815.         set from [mailAddr $from]
  816.         set subject {}
  817.         regexp {Subject: (.*)} [mailGetField subject $folder $id] dummy subject
  818.         set tag {}
  819.         while {[lsearch $inboxMembers $from$tag] >= 0} {
  820.             if {![string length $tag]} {
  821.                 set tag { <2>}
  822.             } else {
  823.                 regexp {[0-9]+} $tag tag
  824.                 set tag " <[expr $tag + 1]>"
  825.             }
  826.         }
  827.         append text [format "%-40s : %s\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞In∞$id\r" "$from$tag" $subject]
  828.         lappend inboxMembers $from$tag
  829.     }
  830.     if {![string length $text]} {
  831.         alertnote "No messages!"
  832.         return
  833.     }
  834.     
  835.     if {[set ind [lsearch [winNames] "*Incoming MAILBOX*"]] >= 0} {
  836.         bringToFront [lindex [winNames] $ind]
  837.         setWinInfo read-only 0
  838.         endOfBuffer
  839.         insertText $text
  840.     } else {
  841.         killMailboxWindow
  842.         new -n "* Incoming MAILBOX *" -g $tileLeft $tileTop $defWidth $errorHeight
  843.         global winModes
  844.         set name [lindex [winNames] 0]
  845.         changeMode [set winModes($name) Brws]
  846.     
  847.         insertText "(<cr> to go to message)\r-----\r$text"
  848.     }
  849.     select [nextLineStart [nextLineStart 0]] [nextLineStart [nextLineStart [nextLineStart 0]]]
  850.     setWinInfo dirty 0
  851.     setWinInfo read-only 1
  852.     message ""
  853. }
  854.  
  855.  
  856. proc getMsgIDs {text} {
  857.     if {[regexp -indices {seld:([0-9]+)} $text dummy ind]} {
  858.         return [concat [string range $text [lindex $ind 0] [lindex $ind 1]] [getMsgIDs [string range $text [lindex $ind 1] end]]]
  859.     }
  860. }
  861.  
  862. proc startNotifying {} {
  863.     global HOME ALPHA quitHooks
  864.     
  865.     AEBuild 'CSOm' CSOm nIns ---- [makeAlis "$HOME:$ALPHA"]
  866. #     lappend quitHooks stopNotifying
  867. }
  868.  
  869. proc stopNotifying {} {
  870.     global HOME ALPHA
  871.     
  872.     AEBuild 'CSOm' CSOm nRem ---- [makeAlis "$HOME:$ALPHA"]
  873. }
  874.